package cn.eeepay.framework.service.impl;

import cn.eeepay.boss.action.RouterOrgAction;
import cn.eeepay.boss.system.websocket.SpringWebSocketHandler;
import cn.eeepay.framework.dao.RouterOrgDao;
import cn.eeepay.framework.dao.TransRouteGroupDao;
import cn.eeepay.framework.dao.sysUser.ExportManageDao;
import cn.eeepay.framework.db.pagination.Page;
import cn.eeepay.framework.model.ExportManage;
import cn.eeepay.framework.model.SysDict;
import cn.eeepay.framework.model.TransRouteGroup;
import cn.eeepay.framework.service.RouterOrgService;
import cn.eeepay.framework.service.SysDictService;
import cn.eeepay.framework.serviceImpl.exportBigData.ExportBase;
import cn.eeepay.framework.serviceImpl.sysUser.DataSourceSwitch;
import cn.eeepay.framework.util.CellUtil;
import cn.eeepay.framework.util.DateUtil;
import cn.eeepay.framework.util.FileUtil;
import cn.eeepay.framework.util.StringUtil;
import com.alibaba.fastjson.JSON;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.socket.TextMessage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 集群中收单商户service实现
 * 
 * @author junhu
 *
 */
@Service
@Transactional
public class RouterOrgServiceImpl implements RouterOrgService {

	@Resource
	private RouterOrgDao routerOrgDao;
	@Resource
	private TransRouteGroupDao transRouteGroupDao;
	@Resource
	private SysDictService sysDictService;
	@Resource
	private DataSourceSwitch dataSourceSwitch;
	@Resource
	private ExportManageDao exportManageDao;



	private static final Logger log = LoggerFactory.getLogger(RouterOrgServiceImpl.class);

	@Bean
	public SpringWebSocketHandler infoHandler() {
		return new SpringWebSocketHandler();
	}

	private String getQuotaStatusStr(Integer quotaStatus) {
		if(quotaStatus==null){
			return "";
		}
		switch (quotaStatus){
			case 2:
				return "否";
			case 1:
				return "是";
			default:
				return "";
		}
	}

	private String getAcqStatusStr(Integer acqStatus) {
		if(acqStatus==null){
			return "";
		}
		switch (acqStatus){
			case 0:
				return "关闭";
			case 1:
				return "开启";
			default:
				return "";
		}
	}


	/**
	 *
	 * @param param
	 * @return
	 */
	public List<Map<String, String>> getDataList(String param, int pageSize, int pageFirst) {
		List<Map<String, String>> data = new ArrayList<Map<String, String>>();

		Map<String, Object> jsonMap = JSON.parseObject(param, HashMap.class);
		jsonMap.put("pageSize", pageSize);
		jsonMap.put("pageFirst", pageFirst);

		List<Map<String, Object>> list = selecrAllInfoRecordInfo(jsonMap);
		if(list!=null){
			for (int i = 0; i < list.size(); i++) {
				Map<String,Object> map = list.get(i);
				Map<String,String> map1=new HashMap<>();
				map1.put("acqMerchantNo", StringUtil.filterNull(map.get("acq_merchant_no")));
				map1.put("acqMerchantName", StringUtil.filterNull(map.get("acq_merchant_name")));
				map1.put("acqMerchantTypeStr", StringUtil.filterNull(map.get("acq_merchant_type_str")));
				map1.put("groupCode", StringUtil.filterNull(map.get("group_code")));
				map1.put("groupName", StringUtil.filterNull(map.get("group_name")));
				map1.put("acqEnname", StringUtil.filterNull(map.get("acq_enname")));
				map1.put("agentName", StringUtil.filterNull(map.get("agent_name")));
				map1.put("groupProvince", StringUtil.filterNull(map.get("group_province")));
				map1.put("groupCity", StringUtil.filterNull(map.get("group_city")));
				map1.put("jRate", map.get("j_rate")==null?"":StringUtil.filterNull(map.get("j_rate"))+"%");
				map1.put("xRate", map.get("x_rate")==null?"":StringUtil.filterNull(map.get("x_rate"))+"%");

				data.add(map1);
			}
		}
		return data;
	}


	/**
	 * 导出excel
	 *
	 * @param param
	 * @param exportFolder
	 * @param response
	 * @throws IOException
	 */
	private void exportData(String param,String exportFolder, HttpServletResponse response) throws IOException {
		//key 加密
		SXSSFWorkbook wb = new SXSSFWorkbook(100);
		Sheet sheet = wb.createSheet("Sheet1");
		double[] cellWidth=null;


		String[] cols = new String[]{"acqMerchantNo","acqMerchantName","acqMerchantTypeStr","groupCode","groupName","acqEnname","agentName","groupProvince","groupCity","jRate","xRate"};
		String[] colsName = new String[]{"收单机构商户编号","商户名称","收单机构商户类别","集群编号","集群名称","收单机构","代理商名称","经营省份","经营市区","收单服务借记卡费率","收单服务贷记卡费率"};

		int rowIdx=0;
		ExportBase.builTitle(wb,sheet,cellWidth,rowIdx,colsName);
		int pageNo=1;
		int pageSize=50000;
		SysDict sysDict=sysDictService.getByKey("EXOPRT_PAGESIZE");
		if(sysDict!=null){
			pageSize=Integer.parseInt(sysDict.getSysValue());
		}


		while (true){
			//page.setPageSize(pageSize);
			int pageFirst = (pageNo - 1) * pageSize;
			//param.put
			//查询集群收单机构商户
			List<Map<String, String>> list = getDataList(param, pageSize, pageFirst);
			if(list!=null&&list.size()>0){
				rowIdx= ExportBase.writeData(wb,sheet,rowIdx,list,cols);
				pageNo=pageNo+1;
			}else{
				break;
			}
		}

		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
		String excelFolder = exportFolder+File.separator+"集群收单商户导出" + sdf.format(new Date()) + ".xlsx";
		File excelFile = new File(excelFolder);
		FileUtil.createFolder(excelFile,1);
		log.info("fileName = " + excelFile.getPath() + " = " + excelFile.getName());
		if (response != null) {
			OutputStream ouputStream =null;
			try {
				String fileNameFormat = new String(excelFile.getName().getBytes("utf-8"),"ISO-8859-1");
				response.reset();
				response.setContentType("application/msexcel;charset=utf-8");
				response.setHeader("Content-disposition", "attachment;filename="+ fileNameFormat);

				ouputStream = response.getOutputStream();
				wb.write(ouputStream);
				ouputStream.flush();
			}catch (Exception e){
				log.error("导出集群收单商户出现异常：{}",e);
			}finally {
				if(ouputStream != null){
					ouputStream.close();
				}
			}
			return;
		}

		FileOutputStream fileOut = null;
		try {
			fileOut = new FileOutputStream(excelFile);
			wb.write(fileOut);
			fileOut.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			fileOut.close();
		}

	}


	@Override
	public Boolean export(String userName, String md5Key, String param, HttpSession session, HttpServletResponse response) {
		try {
			//切换数据源
			//dataSourceSwitch.switchSlave();
			//SettleOrderInfo info = JSONObject.parseObject(param,SettleOrderInfo.class);

			SysDict sysDict = sysDictService.getByKey(ExportBase.FILE_URL);
			if(sysDict!=null){
				// D:\image\exportFile
				String baseFolder=sysDict.getSysValue()+ File.separator+ExportBase.FILENAME;
				//初始文件目录创建
				String exportFolder=ExportBase.fileBase(baseFolder);
				//导出文件
				exportData(param, exportFolder, response);
			}else{
				log.error("导出存储的文件根目录不存在!");
			}
		} catch (Exception e) {
			log.error("出款明细实时导出异常：{}", e.getMessage());
			e.printStackTrace();
			return false;
		} finally {
			dataSourceSwitch.clearDbType();
		}

		return null;
	}


	/**
	 * 异步导出
	 *
	 * @param userName
	 * @param md5Key
	 * @param param
	 * @param session
	 */
	@Override
	public void syncExport(String userName, String md5Key, String param, HttpSession session) {
		try {
			dataSourceSwitch.switchSlave();//切换数据源
			//SettleOrderInfo info = JSONObject.parseObject(param,SettleOrderInfo.class);
			Map<String, Object> jsonMap = JSON.parseObject(param, HashMap.class);
			long num = selectAllInfoRecordInfoCount(jsonMap);
			//存储基础数据
			ExportManage addInfo=new ExportManage();
			addInfo.setMd5Key(md5Key);
			addInfo.setOperator(userName);
			SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			addInfo.setFilterRemark("创建时间:"+sdf1.format(new Date()));
			addInfo.setFilterStr(param);
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
			String zipName= "集群收单机构商户导出记录"+sdf.format(new Date())+"_"+new Random().nextInt(100000) +".zip";
			addInfo.setFileName(zipName);
			dataSourceSwitch.switchMaster();//切换数据源
			exportManageDao.insertExport(addInfo);
			dataSourceSwitch.switchSlave();//切换数据源

			//校验数据是否过百万
			//Map map=//getCount(info);
			int maxNum=1000000;
			if (num <= 0) {
				addInfo.setStatus(2);
				addInfo.setMsg("导出失败,导出数据为空!");
				dataSourceSwitch.switchMaster();//切换数据源
				exportManageDao.updateExportFaile(addInfo);
				dataSourceSwitch.switchSlave();//切换数据源
				return;
			} else if (num > maxNum) {
				addInfo.setStatus(2);
				addInfo.setMsg("导出失败,数据超过" + maxNum + "条!");
				dataSourceSwitch.switchMaster();//切换数据源
				exportManageDao.updateExportFaile(addInfo);
				dataSourceSwitch.switchSlave();//切换数据源
				return;
			}

			SysDict sysDict = sysDictService.getByKey(ExportBase.FILE_URL);
			if(sysDict!=null){
				String baseFolder=sysDict.getSysValue()+File.separator+ExportBase.FILENAME;// D:\image\exportFile
				//初始文件目录创建
				String exportFolder=ExportBase.fileBase(baseFolder);
				//导出文件
				exportData(param, exportFolder, null);
				//zip打包
				String identificationStr="RouteOrgAcqMerchantExport";
				ExportBase.zipDelete(baseFolder,exportFolder,identificationStr,zipName);
				//存储数据
				addInfo.setStatus(1);
				addInfo.setFileUrl(identificationStr+File.separator+zipName);
				dataSourceSwitch.switchMaster();//切换数据源
				exportManageDao.updateExportStatus(addInfo);
				dataSourceSwitch.switchSlave();//切换数据源

				//给前端发送信息表示下载成功
				infoHandler().sendMessageToUser(session, new TextMessage("有新的下载任务已完成"));
			}else{
				log.error("导出存储的文件根目录不存在!");
			}
		} catch (Exception e) {
			log.error("集群收单机构商户异步导出异常!", e);
		}finally {
			dataSourceSwitch.clearDbType();
		}
	}

	@Override
	public long selectAllInfoRecordInfoCount(Map<String, Object> jsonMap) {
		//returnCount 为统计查询结果条数标识，可以为任意值
		jsonMap.put("returnCount", "returnCount");
		return routerOrgDao.selectAllInfoRecordInfoExportCount(jsonMap);
	}

	@Override
	public List<Map> listRouterAcqMerchantByCon(Map<String, Object> param, Page<Map> page) {

		return routerOrgDao.listRouterAcqMerchantByCon(param, page);
	}

	@Override
	public int deleteRouterAcqMerchantById(Long id) {

		return routerOrgDao.deleteRouterAcqMerchantById(id);
	}

	@Override
	public int updateAcqMerchantQuota(Map<String, Object> param) {

		return routerOrgDao.updateAcqMerchantQuota(param);
	}

	@Override
	public List<Map<String,Object>> selecrAllInfoRecordInfo(Map<String,Object> map) {
		return routerOrgDao.selecrAllInfoRecordInfoExport(map);
	}

	@Override
	public Map<String, Object> routerOrgBatchDelete(MultipartFile file) throws Exception {
		Map<String, Object> msg = new HashMap<>();
		Workbook wb = WorkbookFactory.create(file.getInputStream());
		//读取第一个sheet
		Sheet sheet = wb.getSheetAt(0);
		// 遍历所有单元格，读取单元格
		int row_num = sheet.getLastRowNum();

		List<Map<String,Object>> errorList=new ArrayList<Map<String,Object>>();
		List<Map<String,String>> checkList=new ArrayList<Map<String,String>>();//校验
		List<Map<String,String>> deleteList=new ArrayList<Map<String,String>>();//需要更新的

		for (int i = 1; i <= row_num; i++) {
			Row row = sheet.getRow(i);
			String acqMerchantNo1 = CellUtil.getCellValue(row.getCell(0));//收单机构商户编号
			String groupCode1 = CellUtil.getCellValue(row.getCell(2));//集群编号

			Map<String,Object> errorMap=new HashMap<String,Object>();
			int rowNum=i+1;
			if(acqMerchantNo1==null||"".equals(acqMerchantNo1)){
				errorMap.put("msg","第"+rowNum+"行,收单机构商户编号为空!");
				errorList.add(errorMap);
				continue;
			}
			String acqMerchantNo=acqMerchantNo1.split("\\.")[0];

			if(groupCode1==null||"".equals(groupCode1)){
				errorMap.put("msg","第"+rowNum+"行,集群编号为空!");
				errorList.add(errorMap);
				continue;
			}
			String groupCode=groupCode1.split("\\.")[0];


			//验证重复
			if(existList(checkList,acqMerchantNo,groupCode)){
				errorMap.put("msg","导入失败,第"+rowNum+"行,收单机构商户编号("+acqMerchantNo+"),集群编号("+groupCode+")重复!");
				errorList.add(errorMap);
				continue;
			}else{
				Map<String,String> map=new HashMap<String,String>();
				map.put("acqMerchantNo",acqMerchantNo);
				map.put("groupCode",groupCode);
				checkList.add(map);
			}

			List<Map<String,Object>> oldList = routerOrgDao.getTransRouteGroupAcqMerchant(acqMerchantNo,groupCode);
			if(oldList!=null&&oldList.size()>0){
				Map<String,String> map=new HashMap<String,String>();
				map.put("acqMerchantNo",acqMerchantNo);
				map.put("groupCode",groupCode);
				deleteList.add(map);
			}else{
				errorMap.put("msg", "第"+rowNum+"行,集群编号("+groupCode+")中的收单机构商户编号("+acqMerchantNo+")不存在!");
				errorList.add(errorMap);
				continue;
			}
		}
		int num=0;
		String delNo=null;
		if(deleteList!=null&&deleteList.size()>0){
			delNo= DateUtil.dateToUnixTimestamp()+"";
			for(Map<String,String> item:deleteList){
				item.put("deleteNo",delNo);
				routerOrgDao.insertAcqMerImportDel(item);
				//num=num+routerOrgDao.deleteAcqMer(item.get("acqMerchantNo"),item.get("groupCode"));
			}
		}
		msg.put("errorList", errorList);
		msg.put("status", true);
		msg.put("delNo", delNo);
		msg.put("msg", "总共"+row_num+"条数据,错误数据"+errorList.size()+"条!");
		return msg;
	}

	private boolean existList(List<Map<String,String>> list,String acqMerchantNo,String groupCode){
		if(list!=null&&list.size()>0){
			for(Map<String,String> map:list){
				if(map.get("acqMerchantNo").equals(acqMerchantNo)&&map.get("groupCode").equals(groupCode)){
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public  int selectAcqMerCount(Integer groupCode){
		return routerOrgDao.selectAcqMerCount(groupCode);
	}

	@Override
	public List<Map<String, Object>> deleteBatchCount(List<Map> list){
		List<Map<String, Object>>  jsonlist = new ArrayList<Map<String, Object>>();
		for (Map m : list) {
			Map<String,Object> map=new HashMap<String,Object>();
			boolean flag=true;
			for (Map jsonMap : jsonlist) {
				if(m.get("group_code").toString().equals(jsonMap.get("group_code").toString())){
					flag=false;
					jsonMap.put("acqMerCount",Integer.parseInt(jsonMap.get("acqMerCount").toString())-1);
					break;
				}
			}
			if(flag){
				TransRouteGroup transRouteGroup=transRouteGroupDao.selectByPrimaryKey(Integer.parseInt(m.get("group_code").toString()));
				map.put("group_code",m.get("group_code"));
				map.put("group_name",transRouteGroup.getGroupName());
				map.put("acqMerCount",routerOrgDao.selectAcqMerCount(Integer.parseInt(m.get("group_code").toString())));
				jsonlist.add(map);
			}
		}
		return jsonlist;
	}

	@Override
	public List<Map<String, Object>> deleteImportDelCount(String delNo){
		List<Map> list=routerOrgDao.selectAcqMerImportDel(delNo);
		return this.deleteBatchCount(list);
	}

	@Override
	public int deleteImportDelBatch(String delNo){
		int num=0;
		List<Map> list=routerOrgDao.selectAcqMerImportDel(delNo);
		for (Map m:list){
			num=num+routerOrgDao.deleteAcqMer(m.get("acq_merchant_no").toString(),m.get("group_code").toString());
		}
		routerOrgDao.deleteAcqMerImportDel(delNo);
		return num;
	}

	@Override
	public int deleteAcqMerImportDel(String delNo){
		return routerOrgDao.deleteAcqMerImportDel(delNo);
	}
}
